type U = "a" | "b" | "c"
type Foo = {
  [key in U]: string
}

// type Foo = {
//   a: string
//   b: string
//   c: string
// }

let foo: Foo = {
  a: "a",
  b: "b",
  c: "c",
}

type Person = {
  id: number;
  name: string
}

type PersonKeys = keyof Person & {}

type Person2 = {
  [key in PersonKeys]: Person[key]
}

type User = {
  readonly id: number;
  name: string;
  tel: string;
  address?: string;
}

// type UserKeys = keyof User & {}

type CopyUser = {
  [key in keyof User]:User[key]
}

let u1: CopyUser = {
  id: 1,
  name: "jack",
  tel: "133333333",
  // address:"上海"
}
// u1.id = 2;

type Copy<T extends object> = {
  [key in keyof T]:T[key]
}

const u2: Copy<User> = {
  id: 2,
  name: "rose",
  tel: "1233434",
  address:"cd"
}

type Animal = {
  name: string,
  age: number,
  color: string,
  type:"小猫" | "小狗"
}
const dog: Copy<Animal> = {
  name: "小白",
  age: 3,
  color: "white",
  type:"小狗"
}
// keyof T 键名的类型可以得到一个联合类型 string | number | symbol
type A = keyof any;
// 后面的映射类型，可能会联合模板字符串一起操作，可能会要去keyof any 得到的必须是string类型
type B = keyof any & string